package com.bytesizedhosting.api.android.darthcrap.widgets;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

import com.bytesizedhosting.api.android.darthcrap.Constants;
import com.bytesizedhosting.api.android.darthcrap.R;
import com.bytesizedhosting.api.android.darthcrap.api.APIController;
import com.bytesizedhosting.api.android.darthcrap.api.APIData;
import com.bytesizedhosting.api.android.darthcrap.api.APIController.RetrievalController;
import com.bytesizedhosting.api.android.darthcrap.api.APIController.RetrievalState;
import com.bytesizedhosting.api.android.darthcrap.api.APIData.Account;

public class AccountUsageWidgetProvider extends AppWidgetProvider {
	@Override
	public void onUpdate(Context objContext, AppWidgetManager objManager, int[] arrWidgetIDs) {
		HashMap<Integer,String> mapWidgetServers = new HashMap<Integer,String>();
		for (int intWidgetID : arrWidgetIDs) {
			if (AccountUsageWidgetConfigurator.hasWidgetData(objContext, intWidgetID)) {
				mapWidgetServers.put(intWidgetID, AccountUsageWidgetConfigurator.loadBoxName(objContext, intWidgetID));
			}
		}
		AccountUsageWidgetProvider.pushUpdate(objContext,objManager,mapWidgetServers);
	}
	
	public void onDeleted(Context objContext, int[] arrWidgetIDs) {
		for (int intWidgetID : arrWidgetIDs) {
			AccountUsageWidgetConfigurator.deleteWidgetData(objContext, intWidgetID);			
		}
		super.onDeleted(objContext, arrWidgetIDs);
	}
	
	public static void pushUpdate(Context objContext, AppWidgetManager objManager, int intWidgetID, String strBoxName) {
		HashMap<Integer,String> mapWidgetServers = new HashMap<Integer,String>();
		mapWidgetServers.put(intWidgetID, strBoxName);
		pushUpdate(objContext,objManager,mapWidgetServers);
	}
	
	public static void pushUpdate(Context objContext, AppWidgetManager objManager, HashMap<Integer,String> mapWidgetServers) {
		if (mapWidgetServers.size() > 0) {
			Intent objIntent = new Intent(objContext,AccountUsageWidgetService.class);
			objIntent.putExtra("widgetservers",mapWidgetServers);
			objContext.startService(objIntent);
		}
	}
	
	public static class AccountUsageWidgetService extends Service {
		@Override
		public void onStart(Intent objIntent, int intStartID) {
			handleStart(objIntent);
		}

		@Override
		public int onStartCommand(Intent objIntent, int intFlags, int intStartID) {
			handleStart(objIntent);
			return START_STICKY;
		}

		@Override
		public IBinder onBind(Intent objIntent) {
			// The service doesn't need binding
			Log.v(Constants.TAG, "Service onBind");
			return null;
		}
		
		public void handleStart(final Intent objIntent) {
			if (objIntent == null) return;
			
			final Service objService = this;
			new Thread(new Runnable() {
				//@SuppressWarnings("unchecked")
				@SuppressWarnings("unchecked")
				@Override
				public void run() {
					// RemoteViews into map
					// refreshAll
					
					HashMap<Integer,String> mapWidgetServers = (HashMap<Integer, String>) objIntent.getSerializableExtra("widgetservers");
					HashMap<Integer,RemoteViews> mapWidgetViews = new HashMap<Integer, RemoteViews>();
					for (Map.Entry<Integer, String> objEntry : mapWidgetServers.entrySet()) {
						RemoteViews objRemoteViews = new RemoteViews(objService.getPackageName(),R.layout.account_usage_widget);
						objRemoteViews.setTextViewText(R.id.lblBoxName1, objEntry.getValue());
						objRemoteViews.setTextViewText(R.id.lblBoxName2, objEntry.getValue());
						changeView(objRemoteViews,R.id.vgLoading);
						mapWidgetViews.put(objEntry.getKey(), objRemoteViews);
					}
					
					triggerRefresh(mapWidgetViews);
							
					RetrievalController objController = APIController.retrieve(objService,null,false);
					APIController.RetrievalState objState = objController.getState();
					boolean boolHadRetrievalError = objController.hadError();
					
					if (boolHadRetrievalError) {
						if (objState != RetrievalState.KEYCHECK && objState != RetrievalState.LOADING) {
							if (APIController.loadFile(objService)) {
								boolHadRetrievalError = false;
							}
						}
					}
					
					APIData objData = APIController.getData();
					
					for (Map.Entry<Integer, String> objEntry : mapWidgetServers.entrySet()) {
						boolean boolHadError = boolHadRetrievalError;
						int intMessageID = -1;
						String strBoxName = objEntry.getValue();
						Account objAccount = null;
						RemoteViews objRemoteViews = mapWidgetViews.get(objEntry.getKey());
						
						Log.v(Constants.TAG,objEntry.getKey() + " / " + strBoxName + " / " + new Date().getTime());
						
						if (!boolHadError) {
							for (Account objIteratedAccount : objData.getAccountIterator()) {
								if (objIteratedAccount.getServerName().equalsIgnoreCase(strBoxName)) {
									objAccount = objIteratedAccount;
									break;
								}
							}
							if (objAccount == null) {
								boolHadError = true;
								intMessageID = R.string.widget_accountnotfound;
							}
						}
						
						if (boolHadError) {
							changeView(objRemoteViews,R.id.vgMessage);
							
							if (intMessageID == -1) {
								intMessageID = objState.getErrorMessageID();
								if (intMessageID == -1) {
									intMessageID = R.string.generic_unknownerror;
								}
							}
							objRemoteViews.setTextViewText(R.id.lblMessage, objService.getResources().getString(intMessageID));
						}
						else {
							changeView(objRemoteViews,R.id.vgUsage);
							
							boolean boolOverQuota = (objAccount.getCalculatedQuotaUsage() > objAccount.getCalculatedQuotaSoftLimit()); 
							int intVisibleProgressbarID = (boolOverQuota?R.id.pbUsageRed:R.id.pbUsageGreen);
							int intVisibleProgressbarContainerID = (boolOverQuota?R.id.flUsageRed:R.id.flUsageGreen);
							int intOtherProgressbarContainerID = (boolOverQuota?R.id.flUsageGreen:R.id.flUsageRed);
							
							objRemoteViews.setViewVisibility(intVisibleProgressbarContainerID, View.VISIBLE);
							objRemoteViews.setViewVisibility(intOtherProgressbarContainerID, View.GONE);
							
							DecimalFormat objNumberFormat = new DecimalFormat("#00.00");
							objRemoteViews.setTextViewText(R.id.lblUsage, (objNumberFormat.format(objAccount.getCalculatedQuotaUsage()) + " / " + objNumberFormat.format(objAccount.getCalculatedQuotaSoftLimit())));
							objRemoteViews.setProgressBar(intVisibleProgressbarID, (int)(objAccount.getCalculatedQuotaSoftLimit()*10), (int)Math.min(objAccount.getCalculatedQuotaSoftLimit()*10, objAccount.getCalculatedQuotaUsage()*10), false);
						}
					}
					triggerRefresh(mapWidgetViews);
					objService.stopSelf();
				}
				
				private void changeView(RemoteViews objRemoteViews, int intSectionID) {
					objRemoteViews.setViewVisibility(R.id.vgLoading, ((intSectionID==R.id.vgLoading)?View.VISIBLE:View.GONE));
					objRemoteViews.setViewVisibility(R.id.vgMessage, ((intSectionID==R.id.vgMessage)?View.VISIBLE:View.GONE));
					objRemoteViews.setViewVisibility(R.id.vgUsage  , ((intSectionID==R.id.vgUsage  )?View.VISIBLE:View.GONE));
				}
				
				private void triggerRefresh(HashMap<Integer,RemoteViews> mapWidgetViews) {
					AppWidgetManager objManager = AppWidgetManager.getInstance(objService);
					for (Map.Entry<Integer,RemoteViews> objEntry : mapWidgetViews.entrySet()) {
						try {
							objManager.updateAppWidget(objEntry.getKey(), objEntry.getValue());
						}
						catch (Exception objException) {}
					}
				}
			}).start();
		}
	}
}